# -*- coding: utf-8-unix; fill-column: 95; -*-

###############################################################################################
#
# This file is part of Escapade Trip Planner, a social web application for creating and
# sharing motorcycle roadmaps.
#
# Copyright © 2011, Pierre-François Gomez <pef.gomez@gmail.com>
#
# Escapade Trip Planner is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
#
# Escapade Trip Planner is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with Escapade Trip
# Planner. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################################

import multiprocessing

import cherrypy

import config
import escapade.core

class HTTPService(multiprocessing.Process):
    def __init__(self):
        super(HTTPService, self).__init__()

        cherrypy.config.update({'server.socket_host': config.http_service['host'],
                                'server.socket_port': config.http_service['port'],
                                'log.error_file': 'escapade.log',
                                'log.screen': True})

    def run(self):
        l_static_dir = config.http_service['static_dir']

        cherrypy.quickstart(Root(),
                            "/",
                            {'/api': {'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
                                      'tools.log_headers.on': True},
                             '/': {'tools.staticdir.on': True,
                                   'tools.staticdir.dir': l_static_dir,
                                   'tools.staticdir.index': 'index.html'}})

class Root:
    def __init__(self):
        self.api = API(p_base_uri = '', p_id = 'api')

class API:
    def __init__(self, p_base_uri, p_id):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.map_item = MapItem(p_base_uri = self.uri, p_id = 'map_item')
        self.roadmap = Roadmap(p_base_uri = self.uri, p_id = 'roadmap')
        self.exposed = True

    def GET(self, *p_args, **p_kwargs):
        raise(NotImplementedError)

class MapItem():
    def __init__(self, p_base_uri, p_id):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.store = escapade.core.MapItemStore()
        self.search = MapItemSearch(p_base_uri = self.uri,
                                    p_id = 'search',
                                    p_store = self.store)
        self.exposed = True

    def _cp_dispatch(self, vpath):
        l_id = vpath[0]
        return(MapItemElement(p_base_uri = self.uri,
                              p_id = l_id,
                              p_store = self.store))

class MapItemElement():
    def __init__(self, p_base_uri, p_id, p_store):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.store = p_store
        self.exposed = True

    @cherrypy.tools.json_out()
    def GET(self, *p_args, **p_kwargs):
        #return(self.store.child(self.id).read())
        raise(NotImplementedError)

class MapItemSearch():
    def __init__(self, p_base_uri, p_id, p_store):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.store = p_store
        self.exposed = True

    @cherrypy.tools.json_out()
    def GET(self, *p_args, **p_kwargs):
        #return(self.store.search(*p_args, **p_kwargs))
        raise(NotImplementedError)

class Roadmap():
    def __init__(self, p_base_uri, p_id):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.store = escapade.core.RoadmapStore()
        self.search = RoadmapSearch(p_base_uri = self.uri,
                                    p_id = 'search',
                                    p_store = self.store)
        self.exposed = True

    def _cp_dispatch(self, vpath):
        l_id = vpath[0]
        if self.store.contains(l_id):
            return(RoadmapElement(p_base_uri = self.uri,
                                  p_id = l_id,
                                  p_store = self.store))
        else:
            raise(cherrypy.NotFound())

    @cherrypy.tools.json_in()
    @cherrypy.tools.json_out()
    def POST(self, p_id=None, *p_args, **p_kwargs):
        return(self.store.create(cherrypy.request.json))

    @cherrypy.tools.json_out()
    def GET(self):
        # replace each element id on the fly
        def l_update_id(p_elt):
            p_elt['id'] = self.uri + '/' + p_elt['id']
            return p_elt

        # return a list of all the roadmaps
        return [ l_update_id(elt) for elt in self.store.read() ]

class RoadmapElement():
    def __init__(self, p_base_uri, p_id, p_store):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.store = p_store
        self.exposed = True

    @cherrypy.tools.json_out()
    def GET(self, *p_args, **p_kwargs):
        l_elt = self.store.item(self.id).read()
        l_elt['id'] = self.base_uri + '/' + l_elt['id']
        return(l_elt)

    @cherrypy.tools.json_in()
    @cherrypy.tools.json_out()
    def PUT(self, *p_args, **p_kwargs):
        raise(NotImplementedError)

    @cherrypy.tools.json_in()
    def DELETE(self, *p_args, **p_kwargs):
        raise(NotImplementedError)

class RoadmapSearch():
    def __init__(self, p_base_uri, p_id, p_store):
        self.base_uri = p_base_uri
        self.id = p_id
        self.uri = p_base_uri + '/' + p_id
        self.store = p_store
        self.exposed = True

    @cherrypy.tools.json_out()
    def GET(self, *p_args, **p_kwargs):
        #return(self.store.search(*p_args, **p_kwargs))
        raise(NotImplementedError)
